package org.rainbowinverted.charging.device.connect.bl.server.handler;

import cn.hutool.core.util.HexUtil;
import com.dix.codec.bkv.BKV;
import lombok.extern.slf4j.Slf4j;
import org.rainbowinverted.charging.common.core.Byte2BitUtils;
import org.rainbowinverted.charging.device.connect.bl.server.message.in.BlDeviceGunChargeInfoIn;
import org.rainbowinverted.charging.device.connect.bl.server.message.in.BlDeviceGunInfoIn;
import org.rainbowinverted.charging.device.connect.bl.server.message.in.BlDeviceGunStatusIn;
import org.springframework.stereotype.Component;

/**
 * 充电枪消息处理程序
 *
 * @author huaiping
 */
@Slf4j
@Component
public class BlGunInfoMessageHandler {
    /**
     * 充电枪功率信息解码
     *
     * @param bkv bkv
     */
    public BlDeviceGunChargeInfoIn gunPowerInfoDecode(BKV bkv) {
        // 充电编号
        long chargeNo = Long.parseLong(HexUtil.encodeHexStr(bkv.get(0x0a).getValue()), 16);
        // 瞬时功率，定点一位小数，单位W
        int chargePower = Integer.parseInt(HexUtil.encodeHexStr(bkv.get(0x0b).getValue()), 16);
        // 瞬时电流，定点三位小数，单位A
        int chargeCurrent = Integer.parseInt(HexUtil.encodeHexStr(bkv.get(0x0c).getValue()), 16);
        // 已充电电量，定点三位小数，单位kWH
        int electricity = Integer.parseInt(HexUtil.encodeHexStr(bkv.get(0x0d).getValue()), 16);
        // 充电时间，单位分钟
        long chargedTime = Long.parseLong(HexUtil.encodeHexStr(bkv.get(0x0e).getValue()), 16);
        return BlDeviceGunChargeInfoIn.builder()
                .chargeNo(chargeNo)
                .chargePower(chargePower * 10)
                .chargeCurrent(chargeCurrent / 10)
                .electricity(electricity / 10)
                .chargeTime(chargedTime)
                .build();
    }

    /**
     * 充电枪信息解码
     *
     * @param bkv bkv
     */
    public BlDeviceGunInfoIn gunInfoDecode(BKV bkv) {
        // 枪号
        int gunNo = Integer.parseInt(HexUtil.encodeHexStr(bkv.get(0x08).getValue()));
        /* 充电状态 2 字节
          bit0:过载位 0－正常，1过载
          bit1:过流位 0－正常，1过流
          bit2: 过温    0－正常，1过温
          bit3: 空载 0－正常，1空载
          Bit4:电表故障 0－正常，1－故障
          Bit5:在线状态 0 - 离线    1 - 在线
          Bit6:漏电  0－正常，1－故障
          Bit7:CP状态0－正常，1－异常
          Bit8:充电抢状态
          0－未插入，1－插入
          Bit9-11:充电状态
          0– 空闲
          1 - 充电中
          2 - 充电结束
         */
        byte[] gunStatusByteValue = bkv.get(0x77).getValue();
        return BlDeviceGunInfoIn.of(gunNo, parseByteToGunStatus(gunStatusByteValue));
    }

    /**
     * 解析字节枪状态
     *
     * @param bytes 字节
     * @return {@link BlDeviceGunStatusIn}
     */
    private BlDeviceGunStatusIn parseByteToGunStatus(byte[] bytes) {
        // 将byte转换为bit数组，确保bit是16位
        // 因bit数组方向是从右到左，数组是从左到右，故转换时从bit高位开始转换
        /*
        例：bytes = [01, 20]，其bit值 = 00000001 00100000
            bit bytes[1] = 00100000
            bit bytes[0] = 00000001
            转换成bit数组 = bits = 00000001 00100000
         */
        byte[] part0 = Byte2BitUtils.toBit(bytes[1]);
        byte[] part1 = Byte2BitUtils.toBit(bytes[0]);
        byte[] statusBits = new byte[part0.length + part1.length];
        System.arraycopy(part0, 0, statusBits, 0, part0.length);
        System.arraycopy(part1, 0, statusBits, part0.length, part1.length);

        return BlDeviceGunStatusIn.builder()
                .overload(statusBits[0] == 0x01)
                .overCurrent(statusBits[1] == 0x01)
                .overTemp(statusBits[2] == 0x01)
                .idling(statusBits[3] == 0x01)
                .meterFault(statusBits[4] == 0x01)
                .online(statusBits[5] == 0x01)
                .leakCurrent(statusBits[6] == 0x01)
                .cp(statusBits[7] == 0x01)
                .inserted(statusBits[8] == 0x01)
                .charge(statusBits[9] + statusBits[10] + statusBits[11] == 0x01).build();
    }
}
